﻿using Autofac;
using Common.Core.Extensions;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace Common.EventBus.EventBusRabbitMQ
{
    /// <summary>
    /// RabbitMq消息队列扩展
    /// </summary>
    public static class ServiceCollectionExtensions
    {
        public static List<Type> HandlerTypeList = new List<Type>();
        public static bool IsUseRabbitMQ = false;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configure"></param>
        /// <returns></returns>
        public static IServiceCollection ConfigRabbitMqBus(this IServiceCollection services, Action<RabbitMqOptions> configure)
        {
            services.Configure(configure);
            return services;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="builder"></param>
        /// <returns></returns>
        public static ContainerBuilder RegisterRabbitMqBus(this ContainerBuilder builder)
        { 
            // 是否启用RabbitMQ
            if (IsUseRabbitMQ)
            {
                if (builder == null)
                    throw new ArgumentNullException(nameof(builder));
                builder.RegisterType<ConnectionChannelPool>().As(typeof(IConnectionChannelPool)).SingleInstance().PropertiesAutowired();
                builder.RegisterType<RabbitMqBus>().As(typeof(IQueueBus)).SingleInstance().PropertiesAutowired();
                builder.RegisterType<RabbitMqConsumerClientFactory>().As(typeof(IConsumerClientFactory)).SingleInstance().PropertiesAutowired();
                builder.RegisterType<ConsumerServiceSelector>().As(typeof(IConsumerServiceSelector)).SingleInstance().PropertiesAutowired();
                builder.RegisterType<ConsumerRegister>().As(typeof(IConsumerRegister)).SingleInstance().PropertiesAutowired();
            }
            return builder;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="builder"></param>
        /// <returns></returns>
        public static ContainerBuilder RegisterBusHandler<T>(this ContainerBuilder builder) where T : IQueueHandler
        {
            // 是否启用RabbitMQ
            if (IsUseRabbitMQ)
            {
                var type = typeof(T);
                HandlerTypeList.Add(type);
                builder.RegisterType<T>().InstancePerDependency().PropertiesAutowired();
            }
            return builder;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="builder"></param>
        /// <returns></returns>
        public static ContainerBuilder RegisterBusSyncHandler<T>(this ContainerBuilder builder) where T : IQueueSyncHandler
        {
            // 是否启用RabbitMQ
            if (IsUseRabbitMQ)
            {
                var type = typeof(T);
                HandlerTypeList.Add(type);
                builder.RegisterType<T>().InstancePerDependency().PropertiesAutowired();
            }
            return builder;
        }

        /// <summary>
        /// 自动注册EventBus RabbitMQ
        /// </summary>
        /// <param name="services"></param>
        public static void AddRabbitMqBus(this IServiceCollection services, IConfiguration Configuration)
        {
            // 是否启用RabbitMQ
            IsUseRabbitMQ = Configuration.GetSection("RabbitMQProvider:UseRabbitMQ").Value.ToBool(false);
            if (IsUseRabbitMQ)
            {
                string hostName = Configuration.GetSection("RabbitMQProvider:HostName").Value;
                int port = Configuration.GetSection("RabbitMQProvider:Port").Value.ToInt(5672);
                string userName = Configuration.GetSection("RabbitMQProvider:UserName").Value;
                string password = Configuration.GetSection("RabbitMQProvider:Password").Value;
                string virtualHost = Configuration.GetSection("RabbitMQProvider:VirtualHost").Value;
                int RetryCount = Configuration.GetSection("RabbitMQProvider:RetryCount").Value.ToInt(5);
                uint requestedFrameMax = Configuration.GetSection("RabbitMQProvider:RequestedFrameMax").Value.ToUInt(1024000);

                services.ConfigRabbitMqBus(x =>
                {
                    x.HostName = hostName;
                    x.Port = port;
                    x.UserName = userName;
                    x.Password = password;
                    x.VirtualHost = virtualHost;
                    x.RetryCount = RetryCount;

                    x.ConnectionFactoryOptions = option =>
                    {
                        option.RequestedChannelMax = 10240;
                        option.RequestedConnectionTimeout = TimeSpan.FromMilliseconds(3000);
                        option.SocketReadTimeout = TimeSpan.FromMilliseconds(300000);
                        option.SocketWriteTimeout = TimeSpan.FromMilliseconds(300000);
                        option.ContinuationTimeout = TimeSpan.FromSeconds(120);
                        option.HandshakeContinuationTimeout = TimeSpan.FromSeconds(180);
                        option.RequestedFrameMax = requestedFrameMax;
                        option.RequestedHeartbeat = TimeSpan.FromSeconds(60);
                        option.AutomaticRecoveryEnabled = true;
                        option.NetworkRecoveryInterval = TimeSpan.FromSeconds(10);
                        option.TopologyRecoveryEnabled = true;
                        option.UseBackgroundThreadsForIO = true;
                        option.DispatchConsumersAsync = true;
                    };
                });
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="builder"></param>
        /// <returns></returns>
        public static void UseRabbitMqBus(this IServiceProvider serviceProvider)
        {
            // 是否启用RabbitMQ
            if (IsUseRabbitMQ)
            {
                var _iconsumerRegister = serviceProvider.GetService<IConsumerRegister>();
                _iconsumerRegister.Start();
            }
        }
    }
}